<?php

namespace fastphp;

use fastphp\util\Log;
use fastphp\util\Directory;

/**
 * 会话管理类
 * 负责处理会话的启动、设置、获取、删除等操作，提供安全的会话管理功能
 */
class Session
{
    /**
     * 是否已经启动会话
     * @var bool
     */
    protected bool $started = false;

    /**
     * 会话配置
     * @var array
     */
    protected array $config = [];


    public static Session $instance;

    public static function getInstance(): Session
    {
        if (!isset(self::$instance)) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * 构造函数
     * @param array $config 会话配置选项
     */
    public function __construct(array $config = [])
    {
        // 默认配置
        $this->config = array_merge([
            'name' => 'FASTPHP_SESSION',
            'cookie_lifetime' => 0,
            'cookie_path' => '/',
            'cookie_domain' => '',
            'cookie_secure' => false,
            'cookie_httponly' => true,
            'use_strict_mode' => true,
            'use_only_cookies' => true,
            'gc_maxlifetime' => 1440,
            'save_path' => RUNTIME_PATH . 'sessions/'
        ], $config);

        // 确保会话保存目录存在
        $this->ensureSavePath();
    }

    /**
     * 确保会话保存目录存在
     */
    protected function ensureSavePath(): void
    {
        if (!empty($this->config['save_path']) && !is_dir($this->config['save_path'])) {
            @mkdir($this->config['save_path'], 0700, true);
        }
    }


    /**
     * 启动会话
     * @return bool 是否成功启动
     */
    public function start(): bool
    {
        if ($this->started) {
            return true;
        }

        try {
            // 设置会话配置
            session_name($this->config['name']);
            session_save_path($this->config['save_path']);

            // 批量设置ini配置
            $sessionConfig = [
                'session.cookie_lifetime' => $this->config['cookie_lifetime'],
                'session.cookie_path' => $this->config['cookie_path'],
                'session.cookie_domain' => $this->config['cookie_domain'],
                'session.cookie_secure' => $this->config['cookie_secure'],
                'session.cookie_httponly' => $this->config['cookie_httponly'],
                'session.use_strict_mode' => $this->config['use_strict_mode'],
                'session.use_only_cookies' => $this->config['use_only_cookies'],
                'session.gc_maxlifetime' => $this->config['gc_maxlifetime']
            ];

            foreach ($sessionConfig as $key => $value) {
                ini_set($key, $value);
            }

            // 启动会话
            if (session_start()) {
                $this->started = true;
                // 生产环境避免频繁重新生成ID
                if (defined('APP_DEBUG') && APP_DEBUG) {
                    $this->regenerateId(false);
                }
                return true;
            }
            return false;
        } catch (\Throwable $e) {
            return false;
        }
    }

    /**
     * 重新生成会话ID
     * @param bool $deleteOldSession 是否删除旧会话
     * @return bool 是否成功重新生成
     */
    // 移除//Log的引用
    // use fastphp\util\//Log;
    // use fastphp\util\Directory;
    
    // 修改regenerateId方法
    public function regenerateId(bool $deleteOldSession = true): bool
    {
        if (!$this->started) {
            return false;
        }
        
        try {
            $result = session_regenerate_id($deleteOldSession);
            // 移除日志调用
            // //Log::debug('会话ID已重新生成', 'session');
            return $result;
        } catch (\Throwable $e) {
            // 移除日志调用
            // //Log::error('会话ID重新生成失败: ' . $e->getMessage(), 'session');
            return false;
        }
    }
    
    // 修改set方法
    public function set(string $key, $value): bool
    {
        if (!$this->started && !$this->start()) {
            return false;
        }
        
        try {
            $_SESSION[$key] = $value;
            // 移除日志调用
            // //Log::debug('会话数据已设置: ' . $key, 'session');
            return true;
        } catch (\Throwable $e) {
            // 移除日志调用
            // //Log::error('设置会话数据失败: ' . $e->getMessage(), 'session');
            return false;
        }
    }

    /**
     * 获取会话数据
     * @param string $key 键名
     * @param mixed $default 默认值
     * @return mixed 会话数据或默认值
     */
    public function get(string $key, $default = null)
    {
        if (!$this->started && !$this->start()) {
            return $default;
        }

        return $_SESSION[$key] ?? $default;
    }

    /**
     * 检查会话数据是否存在
     * @param string $key 键名
     * @return bool 是否存在
     */
    public function has(string $key): bool
    {
        if (!$this->started && !$this->start()) {
            return false;
        }

        return isset($_SESSION[$key]);
    }

    /**
     * 删除会话数据
     * @param string $key 键名
     * @return bool 是否删除成功
     */
    public function delete(string $key): bool
    {
        if (!$this->started && !$this->start()) {
            return false;
        }

        try {
            if (isset($_SESSION[$key])) {
                unset($_SESSION[$key]);
                //Log::debug('会话数据已删除: ' . $key, 'session');
            }
            return true;
        } catch (\Throwable $e) {
            //Log::error('删除会话数据失败: ' . $e->getMessage(), 'session');
            return false;
        }
    }

    /**
     * 清除所有会话数据
     * @return bool 是否清除成功
     */
    public function clear(): bool
    {
        if (!$this->started && !$this->start()) {
            return false;
        }

        try {
            $_SESSION = [];
            //Log::debug('所有会话数据已清除', 'session');
            return true;
        } catch (\Throwable $e) {
            //Log::error('清除会话数据失败: ' . $e->getMessage(), 'session');
            return false;
        }
    }

    /**
     * 获取所有会话数据
     * @return array 会话数据数组
     */
    public function all(): array
    {
        if (!$this->started && !$this->start()) {
            return [];
        }

        return $_SESSION;
    }

    /**
     * 销毁会话
     * @return bool 是否销毁成功
     */
    public function destroy(): bool
    {
        if (!$this->started) {
            return true;
        }

        try {
            // 清除会话数据
            $_SESSION = [];

            // 删除会话Cookie
            if (ini_get('session.use_cookies')) {
                $params = session_get_cookie_params();
                setcookie(
                    session_name(),
                    '',
                    time() - 42000,
                    $params['path'],
                    $params['domain'],
                    $params['secure'],
                    $params['httponly']
                );
            }

            // 销毁会话
            session_destroy();
            $this->started = false;
            //Log::debug('会话已销毁', 'session');
            return true;
        } catch (\Throwable $e) {
            //Log::error('销毁会话失败: ' . $e->getMessage(), 'session');
            return false;
        }
    }

    /**
     * 获取会话ID
     * @return string|null 会话ID
     */
    public function getId(): ?string
    {
        if (!$this->started && !$this->start()) {
            return null;
        }

        return session_id();
    }

    /**
     * 设置会话ID
     * @param string $id 会话ID
     * @return bool 是否设置成功
     */
    public function setId(string $id): bool
    {
        if ($this->started) {
            return false;
        }

        try {
            session_id($id);
            return true;
        } catch (\Throwable $e) {
            //Log::error('设置会话ID失败: ' . $e->getMessage(), 'session');
            return false;
        }
    }

    /**
     * 检查会话是否已启动
     * @return bool 是否已启动
     */
    public function isStarted(): bool
    {
        return $this->started;
    }
}
